﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ErrorCode
{
    /// <summary>
    /// 高可用分页返回类
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    public class ApiPaging<T>
    {
        /// <summary>
        /// 当前页码（从1开始）
        /// </summary>
        public int PageIndex { get; set; }

        /// <summary>
        /// 每页大小
        /// </summary>
        public int PageSize { get; set; }

        /// <summary>
        /// 总记录数
        /// </summary>
        public int TotalCount { get; set; }

        /// <summary>
        /// 总页数
        /// </summary>
        public int TotalPages { get; set; }

        /// <summary>
        /// 是否有上一页
        /// </summary>
        public bool HasPrevious => PageIndex > 1;

        /// <summary>
        /// 是否有下一页
        /// </summary>
        public bool HasNext => PageIndex < TotalPages;

        /// <summary>
        /// 当前页数据
        /// </summary>
        public List<T> Data { get; set; } = new List<T>();

        /// <summary>
        /// 当前页记录数
        /// </summary>
        public int CurrentPageSize => Data?.Count ?? 0;

        /// <summary>
        /// 是否为首页
        /// </summary>
        public bool IsFirstPage => PageIndex == 1;

        /// <summary>
        /// 是否为末页
        /// </summary>
        public bool IsLastPage => PageIndex == TotalPages || TotalPages == 0;

        /// <summary>
        /// 起始记录索引（从1开始）
        /// </summary>
        public int StartIndex => TotalCount == 0 ? 0 : (PageIndex - 1) * PageSize + 1;

        /// <summary>
        /// 结束记录索引
        /// </summary>
        public int EndIndex => Math.Min(StartIndex + PageSize - 1, TotalCount);

        /// <summary>
        /// 构造函数
        /// </summary>
        public ApiPaging()
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="totalCount">总记录数</param>
        /// <param name="data">数据</param>
        public ApiPaging(int pageIndex, int pageSize, int totalCount, List<T> data)
        {
            PageIndex = pageIndex;
            PageSize = pageSize;
            TotalCount = totalCount;
            Data = data ?? new List<T>();
            TotalPages = (int)Math.Ceiling((double)totalCount / pageSize);
        }

        /// <summary>
        /// 创建分页结果
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="totalCount">总记录数</param>
        /// <returns>分页结果</returns>
        public static ApiPaging<T> Create(List<T> data, int pageIndex, int pageSize, int totalCount)
        {
            return new ApiPaging<T>(pageIndex, pageSize, totalCount, data);
        }

        /// <summary>
        /// 从IQueryable创建分页结果
        /// </summary>
        /// <param name="source">数据源</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <returns>分页结果</returns>
        public static ApiPaging<T> CreateFromQueryable(IQueryable<T> source, int pageIndex, int pageSize)
        {
            var totalCount = source.Count();
            var data = source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            return new ApiPaging<T>(pageIndex, pageSize, totalCount, data);
        }

        /// <summary>
        /// 从IEnumerable创建分页结果
        /// </summary>
        /// <param name="source">数据源</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <returns>分页结果</returns>
        public static ApiPaging<T> CreateFromEnumerable(IEnumerable<T> source, int pageIndex, int pageSize)
        {
            var enumerable = source as T[] ?? source.ToArray();
            var totalCount = enumerable.Length;
            var data = enumerable.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            return new ApiPaging<T>(pageIndex, pageSize, totalCount, data);
        }

        /// <summary>
        /// 创建空的分页结果
        /// </summary>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <returns>空分页结果</returns>
        public static ApiPaging<T> Empty(int pageIndex = 1, int pageSize = 10)
        {
            return new ApiPaging<T>(pageIndex, pageSize, 0, new List<T>());
        }

        /// <summary>
        /// 转换数据类型
        /// </summary>
        /// <typeparam name="TResult">目标类型</typeparam>
        /// <param name="converter">转换函数</param>
        /// <returns>转换后的分页结果</returns>
        public ApiPaging<TResult> Map<TResult>(Func<T, TResult> converter)
        {
            var convertedData = Data.Select(converter).ToList();
            return new ApiPaging<TResult>(PageIndex, PageSize, TotalCount, convertedData);
        }

        /// <summary>
        /// 获取分页信息摘要
        /// </summary>
        /// <returns>分页摘要字符串</returns>
        public string GetPagingSummary()
        {
            if (TotalCount == 0)
                return "暂无数据";

            return $"第 {PageIndex} 页，共 {TotalPages} 页，显示第 {StartIndex}-{EndIndex} 条，共 {TotalCount} 条记录";
        }
    }

    /*
     * 使用示例：
     * 
     * 1. 从 IQueryable 创建分页：
     * var query = _context.TraceabilityInfos.Where(x => !x.IsDeleted);
     * var result = ApiPaging<TraceabilityInfo>.CreateFromQueryable(query, pageIndex: 1, pageSize: 10);
     * 
     * 2. 手动创建分页：
     * var data = new List<TraceabilityInfo> { ... };
     * var result = ApiPaging<TraceabilityInfo>.Create(data, pageIndex: 1, pageSize: 10, totalCount: 100);
     * 
     * 3. 创建空分页：
     * var emptyResult = ApiPaging<TraceabilityInfo>.Empty();
     * 
     * 4. 数据类型转换：
     * var dtoResult = result.Map(x => new TraceabilityInfoDto 
     * { 
     *     Id = x.TraceabilityId, 
     *     Name = x.ProductName 
     * });
     * 
     * 5. 在控制器中使用：
     * [HttpGet]
     * public async Task<ApiResult<ApiPaging<TraceabilityInfo>>> GetTraceabilityInfos(int pageIndex = 1, int pageSize = 10)
     * {
     *     var query = _repository.GetAll().Where(x => !x.IsDeleted);
     *     var pagedResult = ApiPaging<TraceabilityInfo>.CreateFromQueryable(query, pageIndex, pageSize);
     *     
     *     return new ApiResult<ApiPaging<TraceabilityInfo>>
     *     {
     *         Code = ResultCode.成功,
     *         Message = pagedResult.GetPagingSummary(),
     *         Data = pagedResult
     *     };
     * }
     */
}
